package com.xtedu.examproject.controller;

import com.google.gson.Gson;
import com.xtedu.examproject.entity.Classes;
import com.xtedu.examproject.entity.Student;
import com.xtedu.examproject.entity.StudentExamRecordDTO;
import com.xtedu.examproject.entity.UploadedFile;
import com.xtedu.examproject.service.ClassesService;
import com.xtedu.examproject.service.StudentExamRecordService;
import com.xtedu.examproject.service.StudentService;
import com.xtedu.examproject.service.UploadedFileService;
import com.xtedu.examproject.util.DownloadUtil;
import com.xtedu.examproject.util.UploadUtil;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.MultipartConfig;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.Part;

import java.io.*;
import java.util.*;

@MultipartConfig(
        maxFileSize = 1024 * 1024 * 10,
        maxRequestSize = 1024 * 1024 * 10,
        fileSizeThreshold = 1024 * 1024 * 1
)
@WebServlet("/practiceExam/*")
public class PracticeExamServlet extends HttpServlet {

    private StudentService stuService;
    private ClassesService classesService;

    public void init() {
        stuService = new StudentService();
        classesService = new ClassesService();
    }

    /**
     * 提取URL中的action参数（纯工具方法，不执行业务逻辑）
     */
    private String extractActionFromRequest(HttpServletRequest request) {
        // 从URL中提取action参数,默认如果是null,则返回practiceExam,如果不是，则返回对应的 action
        String action = null;
        String pathInfo = request.getPathInfo();

        if (pathInfo != null && pathInfo.length() > 1) {
            action = pathInfo.substring(1);
        } else {
            String uri = request.getRequestURI();
            String contextPath = request.getContextPath();
            String path = uri.substring(contextPath.length());

            int lastSlashIndex = path.lastIndexOf('/');
            if (lastSlashIndex >= 0 && lastSlashIndex < path.length() - 1) {
                action = path.substring(lastSlashIndex + 1);
            }
        }
        return action;
    }

    /**
     * 路由GET请求到相应的显示方法
     */
    private void routeGetRequest(String action, HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        switch (action) {
            case "download":
                DownloadUtil.downloadFile(request, response);
                break;
            default:
                // 默认显示删除页面
                handleDeleteGet(request, response); // 显示删除表单
                break;
        }
    }

    /**
     * 路由POST请求到相应的处理方法
     */
    private void routePostRequest(String action, HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        switch (action) {
            case "upload":
                UploadUtil.uploadFile(request, response);
                break;
            case "batchAdd":
                handleBatchAddPost(request, response);
                break;
            default:
                handleDeletePost(request, response);
                break;
        }
    }

    private void handleDeleteGet(HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        try {
            List<Classes> classes = classesService.findAllClasses();
            List<Student> students = stuService.findAllStudent();
            request.setAttribute("classes", classes);
            request.setAttribute("menuItems", students);

            // 获取学生数据 - 添加异常处理
            List<StudentExamRecordDTO> sers;
            try {
                sers = StudentExamRecordService.getStudentExamRecordsByExamIdAndCourseId(1, 1);
            } catch (Exception e) {
                sers = new ArrayList<>(); // 出错时返回空列表
                System.err.println("获取学生记录失败: " + e.getMessage());
            }
            request.setAttribute("sers", sers);

            // 安全的JSON转换
            String recordsJson = "[]"; // 默认空数组
            try {
                Gson gson = new Gson();
                recordsJson = gson.toJson(sers != null ? sers : new ArrayList<>());
            } catch (Exception e) {
                System.err.println("JSON转换失败: " + e.getMessage());
                recordsJson = "[]";
            }
            request.setAttribute("recordsJson", recordsJson);

            // 转发到JSP页面
            request.getRequestDispatcher("/WEB-INF/views/practiceExam.jsp").forward(request, response);

        } catch (Exception e) {
            System.err.println("handleDeleteGet整体异常: " + e.getMessage());
            e.printStackTrace();
            // 确保页面能加载，即使数据有问题
            request.setAttribute("recordsJson", "[]");
            request.getRequestDispatcher("/WEB-INF/views/practiceExam.jsp").forward(request, response);
        }
    }
    private void handleDeletePost(HttpServletRequest request, HttpServletResponse response)
            throws Exception {
    }


    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //默认是get请求
        String action = extractActionFromRequest(request);
        try {
            routeGetRequest(action, request, response);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String action = extractActionFromRequest(request);
        try {
            routePostRequest(action, request, response);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    // 批量添加处理方法
    // 修改 handleBatchAddPost 方法，保存原始文件名
    private void handleBatchAddPost(HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json");
        PrintWriter out = response.getWriter();
        Map<String, Object> result = new HashMap<>();

        try {
            // 检查是否为 multipart 请求
            if (!request.getContentType().toLowerCase().startsWith("multipart/")) {
                result.put("success", false);
                result.put("message", "请求类型错误");
                out.print(new Gson().toJson(result));
                return;
            }

            java.io.File uploadedFile = null;
            boolean hasHeader = true;
            String originalFileName = null;

            // 获取所有 part
            Collection<Part> parts = request.getParts();

            for (Part part : parts) {
                String partName = part.getName();

                if (partName.equals("hasHeader")) {
                    // 处理普通表单字段
                    BufferedReader reader = new BufferedReader(
                            new InputStreamReader(part.getInputStream(), "UTF-8"));
                    hasHeader = "true".equals(reader.readLine());
                    reader.close();
                } else if (partName.equals("file") && part.getSize() > 0) {
                    // 处理上传的文件
                    originalFileName = part.getSubmittedFileName(); // 获取原始文件名
                    uploadedFile = java.io.File.createTempFile("student_upload_", ".tmp");

                    try (InputStream input = part.getInputStream();
                         FileOutputStream output = new FileOutputStream(uploadedFile)) {
                        byte[] buffer = new byte[1024];
                        int length;
                        while ((length = input.read(buffer)) > 0) {
                            output.write(buffer, 0, length);
                        }
                    }
                }
            }

            if (uploadedFile == null) {
                result.put("success", false);
                result.put("message", "未找到上传文件");
                out.print(new Gson().toJson(result));
                return;
            }

            if (originalFileName == null) {
                result.put("success", false);
                result.put("message", "无法获取文件名");
                out.print(new Gson().toJson(result));
                return;
            }

            // 解析文件并批量插入，传入原始文件名
            BatchImportResult importResult = parseAndImportStudents(uploadedFile, hasHeader, originalFileName);

            // 删除临时文件
            uploadedFile.delete();

            result.put("success", true);
            result.put("message", "批量导入完成");
            result.put("successCount", importResult.getSuccessCount());
            result.put("failCount", importResult.getFailCount());
            result.put("errors", importResult.getErrors());

        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "服务器错误: " + e.getMessage());
        } finally {
            out.print(new Gson().toJson(result));
        }
    }

    // 解析和导入学生数据
    // 修改 parseAndImportStudents 方法，添加原始文件名参数
    private BatchImportResult parseAndImportStudents(java.io.File file, boolean hasHeader, String originalFileName) {
        BatchImportResult result = new BatchImportResult();
        String fileName = originalFileName.toLowerCase(); // 使用原始文件名

        try {
            if (fileName.endsWith(".xlsx") || fileName.endsWith(".xls")) {
                parseExcelFile(file, hasHeader, result);
            } else if (fileName.endsWith(".csv")) {
                parseCsvFile(file, hasHeader, result);
            } else {
                result.addError("不支持的文件格式: " + originalFileName);
            }
        } catch (Exception e) {
            result.addError("文件解析错误: " + e.getMessage());
        }

        return result;
    }

    // 解析Excel文件
    private void parseExcelFile(java.io.File file, boolean hasHeader, BatchImportResult result)
            throws Exception {
        try (java.io.FileInputStream fis = new java.io.FileInputStream(file);
             org.apache.poi.ss.usermodel.Workbook workbook = org.apache.poi.ss.usermodel.WorkbookFactory.create(fis)) {

            org.apache.poi.ss.usermodel.Sheet sheet = workbook.getSheetAt(0);
            java.util.Iterator<org.apache.poi.ss.usermodel.Row> rowIterator = sheet.iterator();

            int rowNum = 0;
            while (rowIterator.hasNext()) {
                org.apache.poi.ss.usermodel.Row row = rowIterator.next();
                rowNum++;

                // 跳过表头
                if (hasHeader && rowNum == 1) {
                    continue;
                }

                // 读取行数据
                if (row.getPhysicalNumberOfCells() >= 7) {
                    String idCard = getCellStringValue(row.getCell(0));
                    String name = getCellStringValue(row.getCell(1));
                    String sex = getCellStringValue(row.getCell(2));
                    String courseId = getCellStringValue(row.getCell(3));
                    String courseName = getCellStringValue(row.getCell(5));
                    String examId = getCellStringValue(row.getCell(6));
                    String examName = getCellStringValue(row.getCell(7));
                    String createDate = getCellStringValue(row.getCell(8));
                    String practiceScore = getCellStringValue(row.getCell(9));
                    // 导入数据
                    importStudentData(idCard, name, sex, courseId, courseName, examId, examName, createDate, practiceScore, result);
                }
            }
        }
    }

    // 解析CSV文件
    private void parseCsvFile(java.io.File file, boolean hasHeader, BatchImportResult result)
            throws Exception {
        // 尝试检测文件编码
        String encoding = detectFileEncoding(file);

        try (java.io.BufferedReader reader = new java.io.BufferedReader(
                new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding))) {

            String line;
            int lineNum = 0;
            while ((line = reader.readLine()) != null) {
                lineNum++;

                if (hasHeader && lineNum == 1) {
                    continue;
                }

                // 使用更健壮的CSV解析
                String[] values = parseCsvLine(line);
                if (values.length >= 8) {
                    importStudentData(
                            values[0].trim(),
                            values[1].trim(),
                            values[2].trim(),
                            values[3].trim(),
                            values[4].trim(),
                            values[5].trim(),
                            values[6].trim(),
                            values[7].trim(),
                            values[8].trim(),
                            result
                    );
                }
            }
        }
    }

    // 检测文件编码
    private String detectFileEncoding(java.io.File file) {
        try (java.io.InputStream input = new java.io.FileInputStream(file)) {
            byte[] bom = new byte[3];
            input.read(bom);

            // 检查BOM标记
            if (bom[0] == (byte) 0xEF && bom[1] == (byte) 0xBB && bom[2] == (byte) 0xBF) {
                return "UTF-8";
            } else if (bom[0] == (byte) 0xFE && bom[1] == (byte) 0xFF) {
                return "UTF-16BE";
            } else if (bom[0] == (byte) 0xFF && bom[1] == (byte) 0xFE) {
                return "UTF-16LE";
            }
        } catch (Exception e) {
            // 忽略错误，使用默认编码
        }
        return "UTF-8"; // 默认编码
    }

    // 更健壮的CSV行解析
    private String[] parseCsvLine(String line) {
        java.util.List<String> values = new java.util.ArrayList<>();
        StringBuilder current = new StringBuilder();
        boolean inQuotes = false;

        for (int i = 0; i < line.length(); i++) {
            char c = line.charAt(i);

            if (c == '"') {
                inQuotes = !inQuotes;
            } else if (c == ',' && !inQuotes) {
                values.add(current.toString().trim());
                current = new StringBuilder();
            } else {
                current.append(c);
            }
        }
        values.add(current.toString().trim());

        return values.toArray(new String[0]);
    }

    // 导入单条数据
    private void importStudentData(String idCard, String name, String genderStr, String courseId, String courseName, String examId, String examName, String createDate, String practiceScoreStr, BatchImportResult result) {
        try {
            // 数据验证
            //practiceScore==-1 表示practiceScore字段为空
            if (idCard == null || idCard.trim().isEmpty() || practiceScoreStr == null || practiceScoreStr.trim().isEmpty() || courseId == null || courseId.trim().isEmpty() || examId == null || examId.trim().isEmpty()) {
                result.addError("缺少必要字段");
                return;
            }

            // 转换数据类型
            int practiceScore = Integer.parseInt(practiceScoreStr.trim());
            int courseIdInt = Integer.parseInt(courseId.trim());
            int examIdInt = Integer.parseInt(examId.trim());
            // 修改数据库
            int id = StudentExamRecordService.updateStudentExamRecordPracticeScore(examIdInt, idCard, courseIdInt, practiceScore);
            if (id > 0) {
                result.incrementSuccessCount();
            } else {
                result.addError("第" + (result.getTotalCount() + 1) + "行: 插入数据库失败");
            }

        } catch (NumberFormatException e) {
            result.addError("第" + (result.getTotalCount() + 1) + "行: 数字格式错误");
        } catch (Exception e) {
            result.addError("第" + (result.getTotalCount() + 1) + "行: " + e.getMessage());
        }
    }

    // 辅助方法：获取单元格字符串值
    private String getCellStringValue(org.apache.poi.ss.usermodel.Cell cell) {
        if (cell == null) {
            return "";
        }
        switch (cell.getCellType()) {
            case STRING:
                return cell.getStringCellValue();
            case NUMERIC:
                if (org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted(cell)) {
                    return new java.text.SimpleDateFormat("yyyy-MM-dd").format(cell.getDateCellValue());
                } else {
                    return String.valueOf((int) cell.getNumericCellValue());
                }
            case BOOLEAN:
                return String.valueOf(cell.getBooleanCellValue());
            case FORMULA:
                return cell.getCellFormula();
            default:
                return "";
        }
    }

    // 批量导入结果类
    class BatchImportResult {
        private int successCount = 0;
        private int failCount = 0;
        private java.util.List<String> errors = new java.util.ArrayList<>();

        public void incrementSuccessCount() {
            successCount++;
        }

        public void addError(String error) {
            errors.add(error);
            failCount++;
        }

        public int getSuccessCount() {
            return successCount;
        }

        public int getFailCount() {
            return failCount;
        }

        public int getTotalCount() {
            return successCount + failCount;
        }

        public java.util.List<String> getErrors() {
            return errors;
        }
    }

}
